package com.quick.android.download;

import android.annotation.SuppressLint;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.util.Base64;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.SocketAddress;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 文件多线程断点下载（自动判断是否支持断点）
 */
public class FileLoaderManager {

    private static final int stuts_finish = 0;
    private static final int stuts_start = 1;

    private static FileLoaderManager manager;

    private Context mContext;
    /**
     * 数据库操作帮助类
     */
    private DBHelper mDBHelper;
    /**
     * 下载缓存目录
     */
    private String mFileDir;
    // 存储了下载状态
    private HashMap<String, Boolean> loadingMap = new HashMap<String, Boolean>();
    private String UA = "Mozilla/4.0 (compatible; MSIE 5.0; Windows XP; DigExt)";
    // 代理服务器
    private String proxyServer;
    // 代理端口
    private int proxyPort;
    // 是否使用代理
    private boolean useProxy;
    // 代理名称
    private String proxyUser;
    // 代理密码
    private String proxyPassword;
    private int blockSize = 1024 * 4; // 4K 一个块
    // 下载集合
    private HashMap<String, FileInfoBean> fileEntities = new HashMap<String, FileInfoBean>();

    private Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            FileInfoBean entity = (FileInfoBean) msg.obj;

            switch (msg.what) {
                case stuts_finish:
                    loadingMap.remove(entity.url);
                    sendMsg(entity, ResultInfoBean.status_sucess, 100);
                    break;
                case stuts_start:
                    synchronized (loadingMap) {
                        if (!loadingMap.get(entity.url)) {
                            loadingMap.remove(entity.url);
                            sendMsg(entity, ResultInfoBean.status_fail, 0);
                            return;
                        }
                    }

                    entity.isSucess = false;
                    if ((entity.id == 0 || entity.again) && entity.length > 0
                            && entity.range) {
                        // 支持断点下载 但是需要重新下载
                        int threads = entity.threads;
                        long length = entity.length;
                        long threadsLength = length / threads;
                        long orther = length % threads;
                        mDBHelper.deleteThreadEntity(entity.id);
                        DownloadThreadGroup downloadGroup = new DownloadThreadGroup(
                                "multi threads reload", entity);
                        for (int i = 0; i < threads; i++) {
                            long begin = i * threadsLength;
                            long end = (i + 1) * threadsLength;
                            if (threads > 1 && i == threads - 1 && orther > 0) {
                                // 如果最后一个线程，有余数，需要修正
                                end = end + orther;
                            }
                            ThreadInfoBean threadEntity = new ThreadInfoBean();
                            threadEntity.start = begin;
                            threadEntity.end = end;
                            threadEntity.load = 0;
                            threadEntity.mFileInfoBean = entity;
                            downloadGroup.setEntity(threadEntity);
                            DownloadThread downloadThread = new DownloadThread(
                                    downloadGroup, threadEntity, entity, i, begin,
                                    end);
                            downloadThread.start();
                        }
                        if (threads > 0) {
                            downloadGroup.start();
                        }
                        return;
                    }
                    if (entity.length <= 0 || !entity.range) {
                        // 不支持断点下载 不管之前下载了多少 都需要重新下载
                        DownloadSingleThread singleThread = new DownloadSingleThread(
                                entity);
                        singleThread.start();
                        return;
                    }
                    if (entity.id != 0 && entity.length > 0 && entity.range) {
                        // 支持断点下载 但是之前下载过一部分
                        List<ThreadInfoBean> entities = entity.threadsEntities;
                        if (entities == null) {
                            return;
                        }
                        int size = entities.size();
                        DownloadThreadGroup downloadGroup = new DownloadThreadGroup(
                                "multi threads continue", entity);
                        for (int i = 0; i < size; i++) {
                            ThreadInfoBean threadEntity = entities.get(i);
                            downloadGroup.setEntity(threadEntity);
                            // 如果起始点加上下载的等于结束的 说明这个线程下载结束
                            if (threadEntity.load + threadEntity.start == threadEntity.end) {
                                continue;
                            }
                            DownloadThread downloadThread = new DownloadThread(
                                    downloadGroup, threadEntity, entity, i,
                                    threadEntity.start, threadEntity.end);
                            downloadThread.start();
                        }
                        downloadGroup.start();
                        mDBHelper.saveOrUpdateFileEntity(entity);
                    }
                    break;
            }
        }

        ;
    };

    public static FileLoaderManager getInstance(Context context) {
        if (manager == null) {
            manager = new FileLoaderManager(context);
        }
        return manager;
    }

    private FileLoaderManager(Context context) {
        mContext = context;
        mDBHelper = new DBHelper(context);
    }

    public String getFileDir() {
        return mFileDir;
    }

    /**
     * 设置下载文件目录
     */
    public void setFileDir(String mDir) {
        this.mFileDir = mDir;
        SimpleUtils.makeDirs(mFileDir);
    }

    public String getProxyUser() {
        return proxyUser;
    }

    /**
     * 代理用户名
     *
     * @param proxyUser
     * @return void
     */
    public void setProxyUser(String proxyUser) {
        this.proxyUser = proxyUser;
    }

    public String getProxyPassword() {
        return proxyPassword;
    }

    /**
     * 设置代理的密码
     *
     * @param proxyPassword
     * @return void
     */
    public void setProxyPassword(String proxyPassword) {
        this.proxyPassword = proxyPassword;
    }

    public String getProxyServer() {
        return proxyServer;
    }

    /**
     * 设置代理服务器
     *
     * @param proxyServer
     * @return void
     */
    public void setProxyServer(String proxyServer) {
        this.proxyServer = proxyServer;
    }

    public int getProxyPort() {
        return proxyPort;
    }

    /**
     * 设置代理端口
     *
     * @param proxyPort
     * @return void
     */
    public void setProxyPort(int proxyPort) {
        this.proxyPort = proxyPort;
    }

    public boolean isUseProxy() {
        return useProxy;
    }

    /**
     * 设置是否使用代理
     *
     * @param useProxy
     * @return void
     */
    public void setUseProxy(boolean useProxy) {
        this.useProxy = useProxy;
    }

    /**
     * 下载文件
     *
     * @param url  请求链接
     * @param path 下载保存到本地文件夹的路径
     * @return void
     */
    public void download(String url, String path) {
        download(url, path, 1, false, null);
    }

    /**
     * 下载文件
     *
     * @param url  请求链接
     * @param path 下载保存到本地文件夹的路径
     * @return void
     */
    public void download(String url) {
        download(url, null, 1, false, null);
    }

    public void download(String url, String path, NotifiInfoBean notfi) {
        download(url, path, 1, false, notfi);
    }

    public void download(String url, NotifiInfoBean notfi) {
        download(url, null, 1, false, notfi);
    }

    /**
     * 下载文件
     *
     * @param url     请求链接
     * @param path    下载保存到本地的位置
     * @param threads 线程数
     * @return void
     */
    public void download(String url, String path, int threads) {
        download(url, path, threads, false, null);
    }

    public void download(String url, int threads) {
        download(url, null, threads, false, null);
    }

    public void download(String url, String path, int threads,
                         NotifiInfoBean notfi) {
        download(url, path, threads, false, notfi);
    }

    public void download(String url, int threads, NotifiInfoBean notfi) {
        download(url, null, threads, false, notfi);
    }

    /**
     * 版本更新下载
     *
     * @param url
     * @param path
     * @return void
     */
    public void downloadUpdate(String url, String path) {
        download(url, path, 1, true, null);
    }

    public void downloadUpdate(String url) {
        download(url, null, 1, true, null);
    }

    public void downloadUpdate(String url, String path, NotifiInfoBean notfi) {
        download(url, path, 1, true, notfi);
    }

    public void downloadUpdate(String url, NotifiInfoBean notfi) {
        download(url, null, 1, true, notfi);
    }

    /**
     * 版本更新下载
     *
     * @param url
     * @param path
     * @param threads 线程数
     * @return void
     */
    public void downloadUpdate(String url, String path, int threads) {
        download(url, path, threads, true, null);
    }

    public void downloadUpdate(String url, int threads) {
        download(url, null, threads, true, null);
    }

    public void downloadUpdate(String url, String path, int threads,
                               NotifiInfoBean notfi) {
        download(url, path, threads, true, notfi);
    }

    public void downloadUpdate(String url, int threads, NotifiInfoBean notfi) {
        download(url, null, threads, true, notfi);
    }

    // 获取正在下载的url
    public Set<String> getLoadingUrl() {
        return fileEntities.keySet();
    }

    // 显示顶部通知栏
    public boolean showNotif(String url, NotifiInfoBean notfi) {
        if (!fileEntities.containsKey(url)) {
            return false;
        }
        FileInfoBean entity = fileEntities.get(url);
        entity.notifi = notfi;
        NotificationHelper helper = new NotificationHelper(mContext,
                notfi.layout_id, notfi.icon_id, notfi.progress_id,
                notfi.progress_txt_id, notfi.clazz);
        entity.helper = helper;
        if (entity.range) {
            helper.initNotif();
        } else {
            helper.downNotification("下载中......");
        }
        return true;
    }

    public void hideNotif(String url) {
        if (!fileEntities.containsKey(url)) {
            return;
        }
        FileInfoBean entity = fileEntities.get(url);
        entity.notifi = null;
        NotificationHelper helper = entity.helper;
        entity.helper = null;
        helper.cancel();
    }

    public void hideNotif() {
        NotificationManager mContextNotificationManager = (NotificationManager) mContext
                .getSystemService(Context.NOTIFICATION_SERVICE);
        mContextNotificationManager.cancelAll();
    }

    /**
     * 停止下载
     *
     * @param url
     * @return void
     */
    public void stop(String url) {
        if (loadingMap.containsKey(url)) {
            loadingMap.put(url, false);
        }
    }

    public List<FileInfoBean> getAllDownload() {
        return mDBHelper.getAllEntity();
    }

    public List<FileInfoBean> getAllFinishDownload() {
        return mDBHelper.getAllFinishEntity();
    }

    public List<FileInfoBean> getAllFailureDownload() {
        return mDBHelper.getAllFailureEntity();
    }

    /**
     * 清除下载
     *
     * @param url
     * @return void
     */
    public void clearByUrl(String url) {
        mDBHelper.deleteFileEntityByUrl(url);
    }

    /**
     * 清除所有历史记录
     *
     * @return void
     */
    public void clearHistory() {
        mDBHelper.deleteAllFileEntity();
        mDBHelper.deleteAllThreadEntity();
    }

    /**
     * 下载文件
     *
     * @param url     请求链接
     * @param path    下载保存到本地的位置
     * @param threads 线程数
     * @return void
     */
    private void download(String url, String path, int threads, boolean update,
                          NotifiInfoBean notfi) {
        // 正在下载中或者停止中
        if (loadingMap.containsKey(url)) {
            return;
        }
        loadingMap.put(url, true);

        if (path == null) {
            if (mFileDir == null) {
                mFileDir = SimpleUtils.getExternalCacheDir(mContext, "files")
                        .getPath();
            }
            path = mFileDir + "/file_" + (System.currentTimeMillis() + "").substring(4);
        }
        File path_file = new File(path);
        if (!path_file.getParentFile().exists()) {
            path_file.getParentFile().mkdirs();
        }
        FileInfoBean fileEntity = mDBHelper.getEntityByUrl(url);
        // 说明之前没有下载
        if (fileEntity == null) {
            fileEntity = new FileInfoBean();
            fileEntity.url = url;
            fileEntity.path = path;
            fileEntity.threads = threads;
        }

        fileEntities.put(url, fileEntity);

        if (notfi != null) {
            NotificationHelper helper = new NotificationHelper(mContext,
                    notfi.layout_id, notfi.icon_id, notfi.progress_id,
                    notfi.progress_txt_id, notfi.clazz);
            helper.initNotif();
            fileEntity.helper = helper;
        }

        fileEntity.notifi = notfi;
        fileEntity.isUpdate = update;
        // 如果下载的文件不存在 那么表示要重新下载
        File old = new File(fileEntity.path);
        if (!old.exists() || old.length() == 0) {
            fileEntity.again = true;
        }
        SimpleUtils.makeDirs(path);
        // 下完了 就直接跳转
        if (fileEntity.path.equals(path) && fileEntity.isSucess
                && !fileEntity.again) {
            fileEntity.notifi = null;
            Message message = handler.obtainMessage();
            message.what = stuts_finish;
            message.obj = fileEntity;
            handler.sendMessage(message);
            return;
        } else if (!fileEntity.path.equals(path) && !fileEntity.again) {
            // 已经下载了 并且文件存在 只需要把文件拷贝过去即可
            final File newfile = new File(path);
            final File oldfile = new File(fileEntity.path);
            File file = newfile.getParentFile();
            if (!file.exists()) {
                file.mkdirs();
            }
            final FileInfoBean newFileEntity = fileEntity;
            final String newPath = path;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    // 文件拷贝以后必须更新数据库
                    // ********************************************************************
                    SimpleUtils.copyFile(oldfile, newfile);
                    newFileEntity.path = newPath;
                    mDBHelper.updateFileEntity(newFileEntity);
                    // ********************************************************************
                    // 如果拷贝之前已经下载完成了 那么发个通知 告诉已经下载完成了
                    if (newFileEntity.isSucess) {
                        // 因为已经本地存在 所以无需通知栏了
                        newFileEntity.notifi = null;
                        Message message = handler.obtainMessage();
                        message.what = stuts_finish;
                        message.obj = newFileEntity;
                        handler.sendMessage(message);
                        return;
                    }
                    // 走到这里说明 情况 1 文件下载了一部分 继续下载 2 文件还未下载
                    // 开启线程 获取服务器支持情况或者
                    GetLengthThread thread = new GetLengthThread(newFileEntity);
                    new Thread(thread).start();
                }
            }).start();
            return;
        }

        // 走到这里说明 情况 1 文件下载了一部分 继续下载 2 文件还未下载
        // 开启线程 获取服务器支持情况或者
        GetLengthThread thread = new GetLengthThread(fileEntity);
        new Thread(thread).start();
    }

    private class GetLengthThread implements Runnable {
        private FileInfoBean fileEntity;

        public GetLengthThread(FileInfoBean fileEntity) {
            this.fileEntity = fileEntity;
        }

        @SuppressLint("NewApi")
        @Override
        public void run() {
            try {
                if (!loadingMap.get(fileEntity.url)) {
                    sendMsg(fileEntity, ResultInfoBean.status_fail, 0);
                    loadingMap.remove(fileEntity.url);
                    return;
                }
                sendMsg(fileEntity, ResultInfoBean.status_start, 0);

                HttpURLConnection connection = getHttpConnection(0,
                        fileEntity.url);

                // --------------------------------------------------------------------------------------
                // 判断是否是重定向地址的办法 有两种
                String redictURL = null;
                Map<String, List<String>> fieldMap = connection
                        .getHeaderFields();
                for (String key : fieldMap.keySet()) {
                    if ("location".equalsIgnoreCase(key)) {
                        redictURL = fieldMap.get(key).get(0);
                        continue;
                    }
                }
                if (redictURL == null) {
                    redictURL = connection.getURL().toString();
                }
                // 说明是重定向
                if (redictURL.startsWith("http")
                        && !redictURL.equals(fileEntity.url)) {
                    connection.disconnect();
                    fileEntity.real_url = redictURL;
                    connection = getHttpConnection(0, redictURL);
                    SimpleUtils.d("下载的文件是重定向地址,正在获取真实地址......");
                }
                int length = connection.getContentLength();
                if (length <= 0) {
                    // 不支持多线程下载,采用单线程下载
                    SimpleUtils.e("服务器不能返回文件大小，采用单线程下载");
                    fileEntity.threads = 1;
                }
                // --------------------------------------------------------------------------------------
                // 是否支持断点
                fileEntity.range = true;
                if (connection.getHeaderField("Content-Range") == null) {
                    SimpleUtils.e("服务器不支持断点续传");
                    fileEntity.range = false;
                }
                connection.disconnect();

                File file = new File(fileEntity.path);
                // 存储空间不够
                if (length > 0 && file.getParentFile().getFreeSpace() < length) {
                    SimpleUtils.e("磁盘空间不够");
                    sendMsg(fileEntity, ResultInfoBean.status_fail, 0);
                    loadingMap.remove(fileEntity.url);
                    return;
                }
                // 文件大小被改变 需要重下
                if (length > 0 && fileEntity.length > 0
                        && fileEntity.length != length) {
                    fileEntity.again = true;
                }
                fileEntity.length = length;

                if (length <= 1024 * 10) {
                    fileEntity.threads = 1;
                }

                Message message = handler.obtainMessage();
                message.what = stuts_start;
                message.obj = fileEntity;
                handler.sendMessage(message);
            } catch (Exception e) {
                if (fileEntity.notifi != null) {
                    NotifiInfoBean notfiEntity = fileEntity.notifi;
                    NotificationHelper helper = new NotificationHelper(
                            mContext, notfiEntity.layout_id,
                            notfiEntity.icon_id, notfiEntity.progress_id,
                            notfiEntity.progress_txt_id, notfiEntity.clazz);
                    helper.initNotif();
                    fileEntity.helper = helper;
                }
                sendMsg(fileEntity, ResultInfoBean.status_fail, 0);
                loadingMap.remove(fileEntity.url);
            }
        }
    }

    private HttpURLConnection getHttpConnection(long pos, String urls)
            throws IOException {
        URL url = new URL(urls);
        HttpURLConnection.setFollowRedirects(false);
        HttpURLConnection httpConnection = null;
        if (useProxy) {
            SocketAddress addr = new InetSocketAddress(proxyServer, proxyPort);
            Proxy proxy = new Proxy(Proxy.Type.HTTP, addr);
            httpConnection = (HttpURLConnection) url.openConnection(proxy);
            if (proxyUser != null && proxyPassword != null) {
                String encoded = new String(Base64.encode(new String(proxyUser
                        + ":" + proxyPassword).getBytes(), Base64.DEFAULT));
                httpConnection.setRequestProperty("Proxy-Authorization",
                        "Basic " + encoded);
            }
        } else {
            httpConnection = (HttpURLConnection) url.openConnection();
        }
        httpConnection.setRequestProperty("Accept-Encoding", "identity");
        httpConnection.setConnectTimeout(10 * 1000);
        httpConnection.setReadTimeout(10 * 1000);
        httpConnection.setRequestProperty("User-Agent", UA);
        if (pos >= 0) {
            httpConnection.setRequestProperty("RANGE", "bytes=" + pos + "-");
        }
        int responseCode = httpConnection.getResponseCode();
        if (responseCode < 200 || responseCode >= 400) {
            loadingMap.remove(urls);
            throw new IOException("服务器返回无效信息:" + responseCode);
        }
        return httpConnection;
    }

    private class DownloadThreadGroup extends ThreadGroup {

        public List<ThreadInfoBean> entitysList = new ArrayList<ThreadInfoBean>();
        private FileInfoBean entity;

        public DownloadThreadGroup(String name, final FileInfoBean entity) {
            super(name);
            this.entity = entity;
        }

        private class DownLoad extends Thread {
            @Override
            public void run() {
                super.run();
                int number = -1;
                while (DownloadThreadGroup.this.activeCount() > 0) {
                    entity.loadedLength = getSize();
                    int progress = (int) (entity.loadedLength * 100 / entity.length);
                    if (number != progress) {
                        sendMsg(entity, ResultInfoBean.status_loading, progress);
                    }
                    number = progress;
                    mDBHelper.saveOrUpdateThreadEntitys(entitysList);
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                    }
                }
                long size = getSize();
                entity.isSucess = true;
                if (size != entity.length) {
                    // 发送下载失败
                    sendMsg(entity, ResultInfoBean.status_fail, 0);
                    entity.isSucess = false;
                } else {
                    // 发送下载进度
                    int price = (int) (size * 100 / entity.length);
                    sendMsg(entity, ResultInfoBean.status_sucess, price);
                }
                loadingMap.remove(entity.url);
                mDBHelper.saveOrUpdateThreadEntitys(entitysList);
                mDBHelper.updateFileEntity(entity);
            }
        }

        private long getSize() {
            int length = entitysList.size();
            long size = 0;
            for (int i = 0; i < length; i++) {
                size = size + entitysList.get(i).load;
            }
            return size;
        }

        public void setEntity(ThreadInfoBean entity) {
            this.entitysList.add(entity);
        }

        public void start() {
            if (entity.notifi != null) {
                NotifiInfoBean notfiEntity = entity.notifi;
                NotificationHelper helper = new NotificationHelper(mContext,
                        notfiEntity.layout_id, notfiEntity.icon_id,
                        notfiEntity.progress_id, notfiEntity.progress_txt_id,
                        notfiEntity.clazz);
                helper.initNotif();
                entity.helper = helper;
            }
            new DownLoad().start();
        }
    }

    private class DownloadThread extends Thread {

        private RandomAccessFile destFile; // 用来实现保存的随机文件
        private long blockBegin = 0; // 开始块
        private long blockEnd = 0; // 结束块
        private long loading;// 绝对指针
        private FileInfoBean entity;
        private ThreadInfoBean threadEntity;
        private long offset;

        public DownloadThread(DownloadThreadGroup group,
                              ThreadInfoBean threadEntity, FileInfoBean entity, int id,
                              long blockBegin, long blockEnd) {
            super(group, "downloadThread-" + id);
            this.blockBegin = blockBegin;
            this.blockEnd = blockEnd;
            this.entity = entity;
            this.threadEntity = threadEntity;
            loading = threadEntity.load;
            offset = blockBegin + loading;
            try {
                destFile = new RandomAccessFile(entity.path, "rw");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

        public void run() {
            BufferedInputStream inputStream = null;
            try {
                destFile.seek(1l * offset);
                HttpURLConnection httpConnection = getHttpConnection(offset,
                        entity.real_url != null ? entity.real_url : entity.url);
                inputStream = new BufferedInputStream(
                        httpConnection.getInputStream());
                byte[] b = new byte[blockSize];
                while (offset < blockEnd) {
                    if (!loadingMap.containsKey(entity.url)
                            || !loadingMap.get(entity.url)) {
                        break;
                    }
                    int read = inputStream.read(b);
                    loading = loading + read;
                    if ((offset = blockBegin + loading) > blockEnd) {
                        loading = blockEnd - blockBegin;
                    }
                    destFile.write(b, 0, read);
                    threadEntity.load = loading;
                }
                SimpleUtils
                        .d("---------------------------------------------------------------------");
                SimpleUtils.d(getName() + "开始：" + blockBegin + "下载了："
                        + loading + "结束：" + blockEnd);
                SimpleUtils
                        .d("---------------------------------------------------------------------");
                httpConnection.disconnect();
                return;
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (inputStream != null)
                        inputStream.close();
                } catch (Exception te) {
                }
                try {
                    if (destFile != null)
                        destFile.close();
                } catch (Exception te) {
                }
            }
        }
    }

    private class DownloadSingleThread extends Thread {

        private RandomAccessFile destFile; // 用来实现保存的随机文件
        private long readCount;// 绝对指针
        private FileInfoBean entity;

        public DownloadSingleThread(FileInfoBean entity) {
            super();
            this.entity = entity;
            try {
                destFile = new RandomAccessFile(entity.path, "rw");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                if (entity.notifi != null) {
                    NotificationHelper helper = entity.helper;
                    helper.downShowNotification("下载失败");
                    entity.helper = helper;
                }
            }
        }

        public void run() {
            BufferedInputStream inputStream = null;
            try {
                destFile.seek(0);
                HttpURLConnection httpConnection = getHttpConnection(-1,
                        entity.real_url != null ? entity.real_url : entity.url);
                inputStream = new BufferedInputStream(
                        httpConnection.getInputStream());

                if (entity.notifi != null && entity.length == 0) {
                    NotifiInfoBean notfiEntity = entity.notifi;
                    NotificationHelper helper = new NotificationHelper(
                            mContext, notfiEntity.layout_id,
                            notfiEntity.icon_id, notfiEntity.progress_id,
                            notfiEntity.progress_txt_id, notfiEntity.clazz);
                    helper.downNotification("下载中...");
                    entity.helper = helper;
                }

                byte[] b = new byte[blockSize];
                int read = 0;
                int number = -1;
                while ((read = inputStream.read(b)) > 0) {
                    if (!loadingMap.get(entity.url)) {
                        // 发送下载失败
                        sendMsg(entity, ResultInfoBean.status_fail, 0);
                        if (entity.notifi != null) {
                            NotificationHelper helper = entity.helper;
                            helper.downShowNotification("下载失败");
                            entity.helper = helper;
                        }
                        entity.isSucess = false;
                        mDBHelper.saveOrUpdateFileEntity(entity);
                        return;
                    }
                    readCount = readCount + read;
                    destFile.write(b, 0, read);

                    entity.loadedLength = readCount;

                    int progress = (int) ((int) (entity.loadedLength * 100 / entity.length));
                    if (number != progress) {
                        sendMsg(entity, ResultInfoBean.status_loading, progress);
                    }
                    number = progress;

                }
                // 发送下载完成通知
                sendMsg(entity, ResultInfoBean.status_sucess, 100);
                if (entity.notifi != null) {
                    NotificationHelper helper = entity.helper;
                    if (entity.isUpdate) {
                        helper.notifyUpdateFinish(new File(entity.path));
                    } else {
                        helper.downShowNotification("下载成功");
                        entity.helper = helper;
                    }
                }
                loadingMap.remove(entity.url);
                entity.isSucess = true;
                mDBHelper.saveOrUpdateFileEntity(entity);
                SimpleUtils
                        .d("---------------------------------------------------------------------");
                SimpleUtils.d("单线程下载:" + readCount);
                SimpleUtils
                        .d("---------------------------------------------------------------------");
                httpConnection.disconnect();
                return;
            } catch (Exception e) {
                sendMsg(entity, ResultInfoBean.status_fail, 100);
            } finally {
                loadingMap.remove(entity.url);
                try {
                    if (inputStream != null)
                        inputStream.close();
                } catch (Exception te) {
                }
                try {
                    if (destFile != null)
                        destFile.close();
                } catch (Exception te) {
                }
            }
        }
    }

    /**
     * 发送广播 更改下载状态
     */
    private void sendMsg(FileInfoBean entity, int status, int progress) {
        SimpleUtils.e("sendMsg:" + entity.toString() + ";status:" + status
                + ";progress:" + progress);
        mDBHelper.saveOrUpdateFileEntity(entity);
        ResultInfoBean resultEntity = new ResultInfoBean();
        resultEntity.range = entity.range;
        resultEntity.url = entity.url;
        resultEntity.loadedLength = entity.loadedLength;
        resultEntity.file = new File(entity.path);
        resultEntity.status = status;
        resultEntity.length = entity.length;
        resultEntity.progress = progress;
        // 异步通知下载完成
        // eventBus.post(resultEntity);

        if (status == ResultInfoBean.status_sucess
                || status == ResultInfoBean.status_fail) {
            fileEntities.remove(entity.url);
        }

        // 下载成功了 但是顶部没有通知栏
        if (entity.notifi == null && entity.isUpdate
                && status == ResultInfoBean.status_sucess) {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setDataAndType(Uri.fromFile(resultEntity.file),
                    "application/vnd.android.package-archive");
            mContext.startActivity(intent);
        }

        // 更新顶部通知栏
        if (entity.notifi != null) {
            NotificationHelper helper = entity.helper;
            switch (status) {
                case ResultInfoBean.status_start:
                    break;
                case ResultInfoBean.status_loading:
                    helper.refreshProgress(progress);
                    break;
                case ResultInfoBean.status_fail:
                    helper.downShowNotification("下载失败");
                    break;
                case ResultInfoBean.status_sucess:
                    if (entity.isUpdate) {
                        helper.notifyUpdateFinish(new File(entity.path));
                    } else {
                        helper.downShowNotification("下载成功");
                    }
                    break;
            }
        }
    }

}
